package com.alibaba.citrus.ots.sales.plan.facade.service.salesplan.publish;

import com.alibaba.citrus.ots.common.annotation.FacadeInvoker;
import com.alibaba.citrus.ots.common.exception.FacadeException;
import com.alibaba.citrus.ots.common.util.CalculatePercentage;
import com.alibaba.citrus.ots.sales.plan.api.salesplan.publish.SalesPlanPublishQueryService;
import com.alibaba.citrus.ots.sales.plan.dto.api.request.DimensionDTO;
import com.alibaba.citrus.ots.sales.plan.dto.api.request.PageQueryPlanScItemExtendRequest;
import com.alibaba.citrus.ots.sales.plan.dto.api.response.SalesPlanScItemStatSubTotalResponse;
import com.alibaba.citrus.ots.sales.plan.facade.service.SalesPlanCommonService;
import com.alibaba.citrus.ots.sales.plan.facade.service.SalesPlanOutCommonService;
import com.alibaba.citrus.ots.sales.plan.model.enums.SalesStatBizTypeEnum;
import com.alibaba.citrus.ots.sales.plan.model.enums.StatPoolTypeEnum;
import com.alibaba.citrus.ots.sales.plan.repository.PlatformEnhanceRepository;
import com.alibaba.citrus.ots.sales.plan.repository.SalesPlanOrganizationRepository;
import com.alibaba.citrus.ots.sales.plan.repository.SalesPlanScItemExtendRepository;
import com.alibaba.citrus.ots.sales.plan.repository.request.OrganizationListQueryRequest;
import com.alibaba.citrus.ots.sales.plan.repository.request.PageQueryPlanScItemExtendRepoRequest;
import com.alibaba.citrus.ots.sales.plan.sdo.SalesPlanSDO;
import com.alibaba.citrus.ots.sales.plan.sdo.SalesPlanScItemExtendSDO;
import com.alibaba.cz.base.tool.log.Log;
import com.alibaba.cz.base.tool.page.PageResult;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.lattice2.epoch.sdk.model.Result;
import com.epoch.app.bcots.model.dto.GetOrganizationSelectsRequest;
import com.epoch.app.bcots.model.dto.GetOrganizationSelectsResponse;
import com.epoch.app.bcots.model.dto.ScItemSDO;
import com.epoch.app.bcots.model.dto.SearchCargoZoneListRequest;
import com.epoch.app.bcots.model.dto.SearchCargoZoneListResponse;
import com.epoch.app.bcots.model.dto.WarehouseInfo;
import com.epoch.app.bcots.service.BaseDataService;
import com.epoch.app.bcots.service.UnifiedInventoryService;
import com.epoch.app.otsunifiedinventory.model.dto.GetCompanyInventoryRequest;
import com.epoch.app.otsunifiedinventory.model.dto.WarehouseInventory;
import com.epoch.app.otsunifiedinventory.service.OtsUnifiedInventoryService;
import com.epoch.app.otsunifiedinventory.service.StockManageService;
import com.google.common.collect.Lists;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author yuhailin
 * @description:
 * @date 2021-09-27 10:37
 */
@Component
public class SalesPlanPublishQueryServiceImpl implements SalesPlanPublishQueryService {

    private static final Log log = Log.getLogger(SalesPlanPublishQueryServiceImpl.class);

    @Resource
    SalesPlanScItemExtendRepository salesPlanScItemExtendRepository;

    @Resource
    SalesPlanCommonService salesPlanCommonService;

    @Resource
    private SalesPlanOrganizationRepository organizationRepository;

    @Resource
    private SalesPlanOutCommonService salesPlanOutCommonService;

    @Resource
    private BaseDataService baseDataService;

    @Resource
    private UnifiedInventoryService unifiedInventoryService;

    @Resource
    private StockManageService stockManageService;

    @Resource
    private PlatformEnhanceRepository platformEnhanceRepository;

    @Resource
    private OtsUnifiedInventoryService otsUnifiedInventoryService;

    @Override
    @FacadeInvoker
    public Result<PageResult<List<SalesPlanScItemExtendSDO>>> pageQueryPlanScItemExtendList(PageQueryPlanScItemExtendRequest pageQueryPlanScItemExtendRequest) {
        SalesPlanSDO salesPlan = salesPlanCommonService.checkSalesPlan(pageQueryPlanScItemExtendRequest.getPlanId());
        PageQueryPlanScItemExtendRepoRequest repoRequest = getRepoRequest(salesPlan, pageQueryPlanScItemExtendRequest);
        PageResult<List<SalesPlanScItemExtendSDO>> listPageResult = salesPlanScItemExtendRepository.pageQueryPlanScItemExtendList(repoRequest);
        if (listPageResult.getContent().size() > 0) {
            listPageResultConverter(listPageResult, salesPlan);
        }
        // 公司任务量要查询公司库存
        String orgBusinessUnitCode = salesPlan.getOrgBusinessUnitCode();
        try {
            refreshStock(listPageResult, pageQueryPlanScItemExtendRequest, orgBusinessUnitCode);
        } catch (Exception e) {
            log.error("月度计划发布查询货品库存异常", e);
        }
        return Result.success(listPageResult);
    }

    /**
     * 公司库存查询
     */
    private void refreshStock(PageResult<List<SalesPlanScItemExtendSDO>> listPageResult, PageQueryPlanScItemExtendRequest pageQueryPlanScItemExtendRequest, String orgBusinessUnitCode) {
        // 公司任务量要查询公司库存
        Integer queryBizType = pageQueryPlanScItemExtendRequest.getQueryBizType();
        List<String> scItemIdList = listPageResult.getContent().stream().map(SalesPlanScItemExtendSDO::getScItemId).collect(Collectors.toList());
        if (SalesStatBizTypeEnum.BUSINESS_UNIT.getOrganizationType().equals(queryBizType)) {
            if (StringUtils.isBlank(orgBusinessUnitCode)) {
                return;
            }
            // 查询公司下的每个货品的库存
            Map<String, String> stockForCompany = getStockForCompany(orgBusinessUnitCode, scItemIdList);
            List<SalesPlanScItemExtendSDO> content = listPageResult.getContent();
            if (MapUtils.isNotEmpty(stockForCompany)) {
                Map<String, String> finalStockMap = stockForCompany;
                content.forEach(salesPlanScItemExtendSDO -> {
                    String scItemId = salesPlanScItemExtendSDO.getScItemId();
                    String availableQuantity = finalStockMap.get(scItemId);
                    salesPlanScItemExtendSDO.setInventoryStr(availableQuantity);
                });
            }
            listPageResult.setContent(content);
        }
    }

    /**
     * 查询公司维度下的货品库存
     * 1、根据公司查销售组织
     * 2、根据销售组织查仓库
     * 3、根据仓库+货品id查仓库里的库存
     * 4、汇总为公司级别
     *
     * @param companyCode  分子公司编码
     * @param scItemIdList 货品idList
     * @return Map(货品id, 公司库存)
     */
    private Map<String, String> getStockForCompany(String companyCode, List<String> scItemIdList) {
        if (org.apache.commons.collections4.CollectionUtils.isEmpty(scItemIdList)) {
            return new HashMap<>();
        }
        // 1、获取分子公司下的销售组织
        GetOrganizationSelectsRequest getOrganizationSelectsRequest = new GetOrganizationSelectsRequest();
        getOrganizationSelectsRequest.setParentId(companyCode);

        log.info("查询业务单元下的销售组织请求参数：{}", JSON.toJSONString(getOrganizationSelectsRequest));
        GetOrganizationSelectsResponse organizationSelects = baseDataService.getOrganizationSelects(getOrganizationSelectsRequest);
        log.info("查询业务单元下的销售组织返回结果：{}", JSON.toJSONString(organizationSelects));
        if (null == organizationSelects) {
            throw new FacadeException("OTS-02-004-01-15-033");
        }
        List orgResult = organizationSelects.getResult();
        if (org.apache.commons.collections4.CollectionUtils.isEmpty(orgResult)) {
            throw new FacadeException("OTS-02-004-01-15-034");
        }
        List<Map> mapList = JSONObject.parseArray(JSON.toJSONString(orgResult), Map.class);
        List<String> orgIdList = mapList.stream().map(map -> map.get("value").toString()).collect(Collectors.toList());
        // 2、根据销售组织查仓库
        SearchCargoZoneListRequest searchCargoZoneListRequest = new SearchCargoZoneListRequest();
        searchCargoZoneListRequest.setModel(3);
        searchCargoZoneListRequest.setStatus(1);
        searchCargoZoneListRequest.setSize(1000);
        searchCargoZoneListRequest.setSaleOrgIdList(orgIdList);
        log.info("查询销售组织下的仓库请求参数：{}", JSON.toJSONString(searchCargoZoneListRequest));
        SearchCargoZoneListResponse searchCargoZoneListResponse = unifiedInventoryService.searchCargoZoneList(searchCargoZoneListRequest);
        log.info("查询销售组织下的仓库返回结果：{}", JSON.toJSONString(searchCargoZoneListResponse));
        if (null == searchCargoZoneListResponse || searchCargoZoneListResponse.getTotal() <= 0
                || org.apache.commons.collections4.CollectionUtils.isEmpty(searchCargoZoneListResponse.getResult())) {
            throw new FacadeException("OTS-02-004-01-15-035");
        }
        List<WarehouseInfo> warehouseInfoList = searchCargoZoneListResponse.getResult();
        List<String> warehouseIdList = warehouseInfoList.stream().map(WarehouseInfo::getId).collect(Collectors.toList());
        // 3、根据仓库+货品id查仓库里的库存
        GetCompanyInventoryRequest getCompanyInventoryRequest = new GetCompanyInventoryRequest();
        getCompanyInventoryRequest.setGoodsIds(scItemIdList);
        getCompanyInventoryRequest.setWarehouseAreaIdList(warehouseIdList);
        Result<List<WarehouseInventory>> listWarehouseStock = otsUnifiedInventoryService.getCompanyInventory(getCompanyInventoryRequest);
        if (null == listWarehouseStock || !listWarehouseStock.isSuccess()) {
            throw new FacadeException("OTS-02-004-01-15-036");
        }
        List<WarehouseInventory> warehouseInventoryList = listWarehouseStock.getResult();
        if (org.apache.commons.collections4.CollectionUtils.isEmpty(warehouseInventoryList)) {
            throw new FacadeException("OTS-02-004-01-15-037");
        }
        // 根据货品id分组  每一个key代表一个货品下的所有仓库的库存量
        Map<String, List<WarehouseInventory>> listMap = warehouseInventoryList.stream().collect(Collectors.groupingBy(WarehouseInventory::getGoodsId));
        Map<String, String> result = new HashMap<>();
        for (String scItemId : listMap.keySet()) {
            List<WarehouseInventory> warehouseInventories = listMap.get(scItemId);
            if (org.apache.commons.collections4.CollectionUtils.isEmpty(warehouseInventories)) {
                continue;
            }
            WarehouseInventory warehouseInventory = warehouseInventories.get(0);
            String availableQuantityFormat = warehouseInventory.getAvailableQuantityFormat();
            // 一个货品在一个仓库只有一个库存
            result.put(scItemId, availableQuantityFormat);
        }
        return result;
    }

    private void listPageResultConverter(PageResult<List<SalesPlanScItemExtendSDO>> listPageResult, SalesPlanSDO salesPlan) {
        //获取货品外部编码
        Set<String> scItemSet = listPageResult.getContent().stream().map(SalesPlanScItemExtendSDO::getScItemId).collect(Collectors.toSet());
        Map<String, ScItemSDO> scItemMapByOutMap = salesPlanOutCommonService.getScItemMapByIds(scItemSet, false);
        listPageResult.getContent().forEach(salesPlanScItemExtendSDO -> {
            if (scItemMapByOutMap != null) {
                ScItemSDO scItemSDO = scItemMapByOutMap.get(salesPlanScItemExtendSDO.getScItemId());
                if (Objects.nonNull(scItemSDO)) {
                    //外部编码
                    salesPlanScItemExtendSDO.setOuterId(scItemSDO.getOuterId());
                }
            }
            salesPlanScItemExtendSDO.setMonthReturnCount(salesPlanScItemExtendSDO.getMonthFirstReturnCount() + salesPlanScItemExtendSDO.getMonthMiddleReturnCount() + salesPlanScItemExtendSDO.getMonthLastReturnCount());
            salesPlanScItemExtendSDO.setMonthAdjustReturnCount(salesPlanScItemExtendSDO.getMonthFirstAdjustReturnCount() + salesPlanScItemExtendSDO.getMonthMiddleAdjustReturnCount() + salesPlanScItemExtendSDO.getMonthLastAdjustReturnCount());
//            if (SalesPlanModelEnum.ADJUST_MODEL.getModel().equals(salesPlanScItemExtendSDO.getModel()) && salesPlanScItemExtendSDO.getCostInsuranceFreight() != 0
//            && salesPlan.getEstimateDiscount() != null){
//                salesPlanScItemExtendSDO.calculateAdjustPublicSatisfaction(salesPlanScItemExtendSDO.getCostInsuranceFreight(),salesPlan.getEstimateDiscount());
//            }
        });
    }

    @Override
    @FacadeInvoker
    public Result<SalesPlanScItemStatSubTotalResponse> queryPublicStat(PageQueryPlanScItemExtendRequest pageQueryPlanScItemExtendRequest) {
        SalesPlanSDO salesPlan = salesPlanCommonService.checkSalesPlan(pageQueryPlanScItemExtendRequest.getPlanId());
        PageQueryPlanScItemExtendRepoRequest repoRequest = getRepoRequest(salesPlan, pageQueryPlanScItemExtendRequest);
        SalesPlanScItemExtendSDO scItemExtendSDO = salesPlanScItemExtendRepository.queryPlanScItemExtendSum(repoRequest);
        if (Objects.isNull(scItemExtendSDO)) {
            throw new FacadeException("OTS-02-004-01-15-007");
        }
        SalesPlanScItemStatSubTotalResponse response = new SalesPlanScItemStatSubTotalResponse();
        response.setMonthCount(scItemExtendSDO.getMonthCount());
        response.setMonthMoney(scItemExtendSDO.getMonthMoney());
        response.setBeforeMonthMoney(scItemExtendSDO.getBeforeMonthMoney());
        response.setTaskCount(scItemExtendSDO.getTaskCount());
        response.setTaskMoney(scItemExtendSDO.getTaskMoney());
        response.setBeforeTaskMoney(scItemExtendSDO.getBeforeTaskMoney());
        response.setAdjustCount(scItemExtendSDO.getAdjustCount());
        response.setAdjustMoney(scItemExtendSDO.getAdjustMoney());
        response.setBeforeAdjustMoney(scItemExtendSDO.getBeforeAdjustMoney());

        response.setReturnCount(scItemExtendSDO.getMonthFirstReturnCount() + scItemExtendSDO.getMonthMiddleReturnCount() + scItemExtendSDO.getMonthLastReturnCount());
        Long monthFirstReturnMoney = Objects.isNull(scItemExtendSDO.getMonthFirstReturnMoney()) ? 0L : scItemExtendSDO.getMonthFirstReturnMoney();
        Long monthMiddleReturnMoney = Objects.isNull(scItemExtendSDO.getMonthMiddleReturnMoney()) ? 0L : scItemExtendSDO.getMonthMiddleReturnMoney();
        Long monthLastReturnMoney = Objects.isNull(scItemExtendSDO.getMonthLastReturnMoney()) ? 0L : scItemExtendSDO.getMonthLastReturnMoney();
        response.setBeforeReturnMoney(monthFirstReturnMoney + monthMiddleReturnMoney + monthLastReturnMoney);
        BigDecimal multiply = salesPlan.getEstimateDiscount().multiply(new BigDecimal("0.01").setScale(2, BigDecimal.ROUND_HALF_UP));
        BigDecimal subtract = new BigDecimal(1).subtract(multiply);
        response.setReturnMoney(new BigDecimal(response.getBeforeReturnMoney()).multiply(subtract).longValue());

        response.setAdjustReturnCount(scItemExtendSDO.getMonthFirstAdjustReturnCount() + scItemExtendSDO.getMonthMiddleAdjustReturnCount() + scItemExtendSDO.getMonthLastAdjustReturnCount());
        Long monthFirstAdjustReturnMoney = Objects.isNull(scItemExtendSDO.getMonthFirstAdjustReturnMoney()) ? 0 : scItemExtendSDO.getMonthFirstAdjustReturnMoney();
        Long monthMiddleAdjustReturnMoney = Objects.isNull(scItemExtendSDO.getMonthMiddleAdjustReturnMoney()) ? 0 : scItemExtendSDO.getMonthMiddleAdjustReturnMoney();
        Long monthLastAdjustReturnMoney = Objects.isNull(scItemExtendSDO.getMonthLastAdjustReturnMoney()) ? 0 : scItemExtendSDO.getMonthLastAdjustReturnMoney();
        response.setBeforeAdjustReturnMoney(Long.valueOf((monthFirstAdjustReturnMoney + monthMiddleAdjustReturnMoney + monthLastAdjustReturnMoney)));
        long beforeAdjustReturnMoney = Objects.isNull(response.getBeforeAdjustReturnMoney()) ? 0 : response.getBeforeAdjustReturnMoney();
        response.setAdjustReturnMoney(new BigDecimal(beforeAdjustReturnMoney).multiply(subtract).longValue());

        response.setMonthContractMoney(scItemExtendSDO.getMonthContractMoney());
        response.setMonthContractCount(scItemExtendSDO.getMonthContractCount());
        response.setBeforeMonthContractMoney(scItemExtendSDO.getBeforeMonthContractMoney());
        //折前满足率(折后任务金额/折后合同金额)
        long taskMoney = Objects.isNull(response.getTaskMoney()) ? 0 : response.getTaskMoney();
        long monthContractMoney = Objects.isNull(response.getMonthContractMoney()) ? 0 : response.getMonthContractMoney();
        BigDecimal beforeSatisfyRate = CalculatePercentage.retainTwoBigDecimalPercentage2(new BigDecimal(taskMoney), new BigDecimal(monthContractMoney));
        response.setBeforeSatisfyRate(beforeSatisfyRate);
        //折后满足率（折后任务金额+折后任务调整回复金额）/折后合同金额
        long adjustReturnMoney = Objects.isNull(response.getAdjustReturnMoney()) ? 0 : response.getAdjustReturnMoney();
        long adjustTaskReturnMoney = taskMoney + adjustReturnMoney;
        BigDecimal satisfyRate = CalculatePercentage.retainTwoBigDecimalPercentage2(new BigDecimal(adjustTaskReturnMoney), new BigDecimal(monthContractMoney));
        response.setSatisfyRate(satisfyRate);
        return Result.success(response);
    }

    private PageQueryPlanScItemExtendRepoRequest getRepoRequest(SalesPlanSDO salesPlan, PageQueryPlanScItemExtendRequest pageQueryPlanScItemExtendRequest) {
        DimensionDTO dimensionDTO = salesPlanCommonService.checkBizType(salesPlan, pageQueryPlanScItemExtendRequest);
        if (pageQueryPlanScItemExtendRequest.getBizType() > pageQueryPlanScItemExtendRequest.getQueryBizType()) {
            throw new FacadeException("OTS-02-004-01-15-008");
        }
        PageQueryPlanScItemExtendRepoRequest extendRepoRequest = new PageQueryPlanScItemExtendRepoRequest();
        BeanUtils.copyProperties(pageQueryPlanScItemExtendRequest, extendRepoRequest);
        extendRepoRequest.setPoolType(StatPoolTypeEnum.SC_ITEM.getPoolType());
        //如果bizType = queryBizType
        if (pageQueryPlanScItemExtendRequest.getBizType().equals(pageQueryPlanScItemExtendRequest.getQueryBizType())) {
            extendRepoRequest.setBizType(dimensionDTO.getBizType());
            extendRepoRequest.setBizId(Lists.newArrayList(dimensionDTO.getBizId()));
        } else {
            SalesStatBizTypeEnum byOrganizationType = SalesStatBizTypeEnum.getByOrganizationType(pageQueryPlanScItemExtendRequest.getQueryBizType());
            if (byOrganizationType == null) {
                throw new FacadeException("OTS-02-002-02-15-007");
            }
            extendRepoRequest.setBizType(byOrganizationType.getBizType());
            OrganizationListQueryRequest organizationListQueryRequest = new OrganizationListQueryRequest();
            if (null != pageQueryPlanScItemExtendRequest.getQueryBizType()) {
                organizationListQueryRequest.setType(pageQueryPlanScItemExtendRequest.getQueryBizType());
            } else {
                organizationListQueryRequest.setType(106);
            }
            organizationListQueryRequest.setId(pageQueryPlanScItemExtendRequest.getBizId());
            List<com.epoch.app.otsplatformenhance.sdo.OrganizationSDO> downOrganizationList = platformEnhanceRepository.getDownOrganizationList(organizationListQueryRequest);
            if (CollectionUtils.isEmpty(downOrganizationList)) {
                throw new FacadeException("OTS-02-004-01-15-030");
            }
            List<String> collect = downOrganizationList.stream().map(com.epoch.app.otsplatformenhance.sdo.OrganizationSDO::getId).collect(Collectors.toList());
/*            List<OrganizationSDO> organizationSDOS = organizationRepository.queryOrganizationAllDeparment(pageQueryPlanScItemExtendRequest.getBizId());
            if (CollectionUtils.isEmpty(organizationSDOS)) {
                throw new FacadeException("OTS-02-004-01-15-030");
            }
            List<String> collect = organizationSDOS.stream().map(OrganizationSDO::getId).collect(Collectors.toList());*/
            extendRepoRequest.setBizId(collect);
        }
        return extendRepoRequest;
    }
}
